package suo;

import suo.utils.ParameterMapping;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class SimpleExecutor implements Executor {

    private Connection connection = null;

    public <E> List<E> query(Configuration configuration, MapperStatement mapperStatement, Object... param) throws SQLException, NoSuchFieldException, IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException {
        PreparedStatement preparedStatement = getPreparedStatement(configuration, mapperStatement, param);
        //执行SQL
        ResultSet resultSet = preparedStatement.executeQuery();
        //映射
        Class<?> resultType = mapperStatement.getResultType();
        ArrayList<E> results = new ArrayList();
        while (resultSet.next()) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            E o = (E) resultType.newInstance();
            int columnCount = metaData.getColumnCount();
            for (int i = 1; i <= columnCount; i++) {
                /*String columnName = metaData.getColumnName(i);
                Object value = resultSet.getObject(columnName);
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultType);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                writeMethod.invoke(o,value);*/

                String columnName = metaData.getColumnName(i);
                //String columnName = metaData.getColumnName(i);
                Object value = resultSet.getObject(columnName);
                //Object value = resultSet.getObject(columnName);
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultType);
                //PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultType);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                //Method writeMethod = propertyDescriptor.getWriteMethod();
                writeMethod.invoke(o, value);
                //writeMethod.invoke(o,value)
            }
            results.add(o);
        }
        return results;
    }

    public void close() throws SQLException {
        connection.close();
    }

    public Integer update(Configuration configuration, MapperStatement mapperStatement, Object[] param) throws SQLException, NoSuchFieldException, IllegalAccessException {
        PreparedStatement preparedStatement = getPreparedStatement(configuration, mapperStatement, param);
        //执行SQL
        int i = preparedStatement.executeUpdate();
        return i;
    }

    private PreparedStatement getPreparedStatement(Configuration configuration, MapperStatement mapperStatement, Object... param) throws SQLException, NoSuchFieldException, IllegalAccessException {
        //获取连接
        connection = configuration.getDataSource().getConnection();
        //获取SQL，SQL语句中带有#{}，${}
        String sql = mapperStatement.getSql();
        //解析SQL
        BoundSql boundSql = BoundSql.getBoundSql(sql);
        //预编译
        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
        //设置参数，映射
        //获取参数类型
        Class<?> paramterType = mapperStatement.getParamterType();
        for (int i = 0; i < boundSql.getParamTye().size(); i++) {
            ParameterMapping parameterMapping = boundSql.getParamTye().get(i);
            String name = parameterMapping.getContent();
            Field declaredField = paramterType.getDeclaredField(name);
            declaredField.setAccessible(true);
            Object o = declaredField.get(param[0]);
            preparedStatement.setObject(i + 1, o);
        }
        return preparedStatement;
    }
}
